package com.blockchain.front.service.content.achieve;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.blockchain.common.enums.ArticleType;
import com.blockchain.common.enums.IsPass;
import com.blockchain.framework.http.upload.FileStore;
import com.blockchain.framework.service.ServiceFactory;
import com.blockchain.framework.service.ServiceResource;
import com.blockchain.framework.service.query.ArrayParser;
import com.blockchain.framework.service.query.EmptyPageResult;
import com.blockchain.framework.service.query.ItemParser;
import com.blockchain.framework.service.query.Paging;
import com.blockchain.framework.service.query.PagingResult;
import com.blockchain.front.service.content.ArticleManage;
import com.blockchain.front.service.content.entity.Article;
import com.blockchain.util.StringHelper;
import com.blockchain.util.parser.EnumParser;
import com.blockchain.variables.P2PConst;

public class ArticleManageImpl extends AbstractConteneService implements
		ArticleManage {

	public static class ArticleManageFactory implements
			ServiceFactory<ArticleManage> {
		@Override
		public ArticleManage newInstance(ServiceResource serviceResource) {
			return new ArticleManageImpl(serviceResource);
		}
	}

	private String getCreater(int creater) throws Throwable {
		try {
			try (Connection connection = getConnection(P2PConst.DB_CONSOLE);
					PreparedStatement pstmt = connection
							.prepareStatement("SELECT F02 FROM T7011 WHERE F01=?")) {
				pstmt.setInt(1, creater);
				try (ResultSet resultSet = pstmt.executeQuery()) {
					if (resultSet.next()) {
						return resultSet.getString(1);
					}
				}
			}
		} catch (Exception e) {

		}
		return "";
	}

	private ArticleType getType(int articleId) throws Throwable {
		try {
			try (Connection connection = getConnection(P2PConst.DB_INFORMATION);
					PreparedStatement pstmt = connection
							.prepareStatement("SELECT F02 FROM T5011 WHERE F01=?")) {
				pstmt.setInt(1, articleId);
				try (ResultSet resultSet = pstmt.executeQuery()) {
					if (resultSet.next()) {
						String s = resultSet.getString(1);
						return EnumParser.parse(ArticleType.class, s);
					}
				}
			}
		} catch (Exception e) {

		}
		return null;
	}

	protected static final ArrayParser<Article> ARRAY_PARSER = new ArrayParser<Article>() {

		@Override
		public Article[] parse(ResultSet rs) throws SQLException {
			ArrayList<Article> list = null;
			while (rs.next()) {
				Article article = new Article();
				article.id = rs.getInt(1);
				article.viewTimes = rs.getInt(2);
				article.title = rs.getString(3);
				article.titleEn = rs.getString(10);
				article.titleTw = rs.getString(11);
				article.source = rs.getString(4);
				article.summary = rs.getString(5);
				article.imageCode = rs.getString(6);
				article.createtime = rs.getTimestamp(7);
				article.publishTime = rs.getTimestamp(8);
				article.creater = rs.getString(9);
				if (list == null) {
					list = new ArrayList<>();
				}
				list.add(article);
			}
			return list == null ? null : list.toArray(new Article[list.size()]);
		}
	};
	protected static final ItemParser<Article> ITEM_PARSER = new ItemParser<Article>() {

		@Override
		public Article parse(ResultSet rs) throws SQLException {
			Article news = new Article();
			if (rs.next()) {
				news.id = rs.getInt(1);
				news.viewTimes = rs.getInt(2);
				news.title = rs.getString(3);
				news.titleEn = rs.getString(10);
				news.titleTw = rs.getString(11);
				news.source = rs.getString(4);
				news.summary = rs.getString(5);
				news.imageCode = rs.getString(6);
				news.createtime = rs.getTimestamp(7);
				news.publishTime = rs.getTimestamp(8);
				news.creater = rs.getString(9);
			}
			return news;
		}
	};
	protected static final String SELECT_ALL_SQL = "SELECT F01,F03,F06,F07,F08,F09,F11,F12,F10,F16,F17 FROM T5011 ";

	public ArticleManageImpl(ServiceResource serviceResource) {
		super(serviceResource);
	}

	@Override
	public Article get(int id) throws Throwable {
		if (id <= 0) {
			return null;
		}
		StringBuffer sql = new StringBuffer();
		sql.append(SELECT_ALL_SQL);
		sql.append(" WHERE F01  =? AND F05  =?");
		return select(getConnection(), ITEM_PARSER, sql.toString(), id,
				IsPass.S.name());
	}

	@Override
	public PagingResult<Article> search(ArticleType articleType, Paging paging)
			throws Throwable {
		if (articleType == null) {
			return new EmptyPageResult<Article>();
		}
		StringBuilder sql = new StringBuilder(SELECT_ALL_SQL);
		sql.append(" WHERE F05 = ?  AND F02 = ? ");
		sql.append("ORDER BY F12 DESC,F04 DESC");
		PagingResult<Article> pr = selectPaging(getConnection(), ARRAY_PARSER,
				paging, sql.toString(), IsPass.S.name(),
				articleType);
		if (pr != null&&pr.getItems()!=null) {
			for (Article a : pr.getItems()) {
				String c = getCreater(Integer.parseInt(a.creater));
				a.creater = c;
			}
		}

		return pr;
	}

	@Override
	public String getContent(int id) throws Throwable {
		if (id <= 0) {
			return null;
		}
		String content = null;
		try (Connection connection = getConnection();
				PreparedStatement pstmt = connection
						.prepareStatement("SELECT T5011_1.F02 FROM T5011_1 INNER JOIN T5011 ON T5011.F01 = T5011_1.F01 WHERE T5011_1.F01 = ? ")) {
			pstmt.setInt(1, id);
			try (ResultSet resultSet = pstmt.executeQuery()) {
				if (resultSet.next()) {
					content = resultSet.getString(1);
				}
			}
		}
		content = filterTag(content);
		return content;
	}
	
	@Override
	public String getContentEn(int id) throws Throwable {
		if (id <= 0) {
			return null;
		}
		String content = null;
		try (Connection connection = getConnection();
				PreparedStatement pstmt = connection
						.prepareStatement("SELECT T5011_1.F03 FROM T5011_1 INNER JOIN T5011 ON T5011.F01 = T5011_1.F01 WHERE T5011_1.F01 = ? ")) {
			pstmt.setInt(1, id);
			try (ResultSet resultSet = pstmt.executeQuery()) {
				if (resultSet.next()) {
					content = resultSet.getString(1);
				}
			}
		}
		content = filterTag(content);
		return content;
	}
	
	@Override
	public String getContentTw(int id) throws Throwable {
		if (id <= 0) {
			return null;
		}
		String content = null;
		try (Connection connection = getConnection();
				PreparedStatement pstmt = connection
						.prepareStatement("SELECT T5011_1.F04 FROM T5011_1 INNER JOIN T5011 ON T5011.F01 = T5011_1.F01 WHERE T5011_1.F01 = ? ")) {
			pstmt.setInt(1, id);
			try (ResultSet resultSet = pstmt.executeQuery()) {
				if (resultSet.next()) {
					content = resultSet.getString(1);
				}
			}
		}
		content = filterTag(content);
		return content;
	}
	
	@Override
	public void view(int id) throws Throwable {
		if (id <= 0) {
			return;
		}
		execute(getConnection(),
				"UPDATE T5011 SET F03 = F03 + 1 WHERE F01 = ? ", id);
	}

	@Override
	public Article get(String articleType) throws Throwable {
		if (articleType == null) {
			return null;
		}
		StringBuffer sql = new StringBuffer();
		sql.append(SELECT_ALL_SQL);
		sql.append(" WHERE F02 = ? AND F05  =? ORDER BY F04 DESC LIMIT 1");
		return select(getConnection(), ITEM_PARSER, sql.toString(),
				articleType,IsPass.S.name());
	}

	@Override
	public String getContent(ArticleType articleType) throws Throwable {
		if (articleType == null) {
			return null;
		}
		String content = null;
		try (Connection connection = getConnection()) {
			int id;
			try (PreparedStatement pstmt = connection
					.prepareStatement("SELECT F01 FROM T5011 WHERE T5011.F02 = ? AND T5011.F05 = ? ORDER BY F04 DESC LIMIT 1")) {
				pstmt.setString(1, articleType.name());
				pstmt.setString(2, IsPass.S.name());
				try (ResultSet resultSet = pstmt.executeQuery()) {
					if (resultSet.next()) {
						id = resultSet.getInt(1);
					} else {
						return null;
					}
				}
			}
			try (PreparedStatement pstmt = connection
					.prepareStatement("SELECT T5011_1.F02 FROM T5011_1 INNER JOIN T5011 ON T5011.F01 = T5011_1.F01 WHERE T5011_1.F01 = ? ")) {
				pstmt.setInt(1, id);
				try (ResultSet resultSet = pstmt.executeQuery()) {
					if (resultSet.next()) {
						content = resultSet.getString(1);
					}
				}
			}
		}
		content = filterTag(content);
		return content;
	}

	/**
	 * 替换关键字
	 * 
	 * @param content
	 * @return
	 * @throws Throwable
	 */
	private static final Pattern[] REPLACE_TAG_PATTERN = {
			Pattern.compile("\\<img.*?\\>", 2),
			Pattern.compile("\\<a(.*)\\>(.*)\\<\\/a\\>", 2) };

	private String filterTag(String content) throws Throwable {
		ArrayList<String> KEYS = new ArrayList<String>();
		ArrayList<String> HREFS = new ArrayList<String>();
		HashMap<Integer, String[]> hm = new HashMap<Integer, String[]>();

		FileStore fileStore = serviceResource.getResource(FileStore.class);
		StringBuffer sb = new StringBuffer();
		StringHelper.format(sb, content, fileStore);
		content = sb.toString();

		for (Pattern p : REPLACE_TAG_PATTERN) {
			Matcher matcher = p.matcher(content);
			while (matcher.find()) {
				String key = matcher.group();
				Integer idx = sort(hm, content, key, 0);
				if (idx != null && idx >= 0) {
					String[] keys = { key, key };
					hm.put(idx, keys);
				}
			}
		}

		/*try (Connection connection = getConnection(P2PConst.DB_CONSOLE);
				PreparedStatement pstmt = connection
						.prepareStatement("SELECT F02,F03 FROM T7059 WHERE F05 = ? ORDER BY LENGTH(F02) DESC ")) {
			pstmt.setString(1, IsPass.S.name());
			try (ResultSet resultSet = pstmt.executeQuery()) {
				while (resultSet.next()) {
					KEYS.add(resultSet.getString(1));
					HREFS.add(resultSet.getString(2));
				}
			}
		}*/

		int size = 0;
		if (content != null && KEYS.size() > 0) {

			for (int i = 0; i < KEYS.size(); i++) {
				String key = KEYS.get(i);
				Integer idx = sort(hm, content, key, 0);
				if (idx != null) {
					String key2 = "<a href='" + HREFS.get(i)
							+ "' target='_blank' class='blue'>" + key + "</a>";
					String[] values = { key, key2 };
					hm.put(idx, values);
					size++;
					if (size == 5) {
						break;
					}
				}
			}

			List<Map.Entry<Integer, String[]>> infoIds = new ArrayList<Map.Entry<Integer, String[]>>(
					hm.entrySet());
			// 排序
			Collections.sort(infoIds,
					new Comparator<Map.Entry<Integer, String[]>>() {
						public int compare(Map.Entry<Integer, String[]> o1,
								Map.Entry<Integer, String[]> o2) {
							return (o1.getKey() - o2.getKey());
						}
					});

			StringBuffer s = new StringBuffer();
			int index = 0;
			for (int i = 0; i < infoIds.size(); i++) {
				int start = infoIds.get(i).getKey();
				String[] values = infoIds.get(i).getValue();
				// System.out.println("content.length:"+content.length()+" index:"+index+" start:"+start+" length:"+values[0].length());
				// System.out.println(values[0]);
				s.append(content.substring(index, start));
				s.append(values[1]);
				index = start + values[0].length();
			}
			if (index < content.length()) {
				s.append(content.substring(index));
			}
			content = s.toString();
		}

		return content;
	}

	private Integer sort(HashMap<Integer, String[]> hm, String content,
			String key, int index) {
		if (content.length() <= index) {
			return null;
		}
		int idx = content.indexOf(key, index);
		if (idx < 0) {
			return null;
		}

		List<Map.Entry<Integer, String[]>> infoIds = new ArrayList<Map.Entry<Integer, String[]>>(
				hm.entrySet());
		// 排序
		Collections.sort(infoIds,
				new Comparator<Map.Entry<Integer, String[]>>() {
					public int compare(Map.Entry<Integer, String[]> o1,
							Map.Entry<Integer, String[]> o2) {
						return (o1.getKey() - o2.getKey());
					}
				});

		for (int i = 0; i < infoIds.size(); i++) {
			int start = infoIds.get(i).getKey();
			String[] value = infoIds.get(i).getValue();
			int end = start + value[0].length();

			if ((idx > end || start > (idx + key.length()))) {
			} else {
				if (end < idx + key.length()) {
					end = idx + key.length();
				}
				return sort(hm, content, key, end);
			}
		}
		return new Integer(idx);
	}

	@Override
	public Article get(int id, ArticleType articleType) throws Throwable {
		if (id <= 0 || articleType == null) {
			return null;
		}
		StringBuffer sql = new StringBuffer();
		sql.append(SELECT_ALL_SQL);
		sql.append(" WHERE F01  =? AND F02 = ?");
		Article a = select(getConnection(), ITEM_PARSER, sql.toString(), id,
				articleType);
		String c = "";
		if(Integer.parseInt(a.creater)>0){
			c=getCreater(Integer.parseInt(a.creater));
		}
		a.creater = c;
		return a;
	}

	@Override
	public Article gets(int id) throws Throwable {
		if (id <= 0) {
			return null;
		}
		StringBuffer sql = new StringBuffer();
		sql.append(SELECT_ALL_SQL);
		sql.append(" WHERE F01  =? AND F05  =?");
		Article a = select(getConnection(), ITEM_PARSER, sql.toString(), id,
				IsPass.S);
		String c = getCreater(Integer.parseInt(a.creater));
		a.creater = c;
		return a;
	}

	@Override
	public Timestamp getTimestamp(String type) throws Throwable {
		return selectTimestamp(P2PConst.DB_INFORMATION, "SELECT F11 FROM T5011 WHERE F02=?", type);
	}
}
